﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Itasa.API
{
    internal class Show : IComparable, IComparable<Show>
    {

        public enum Order { LastSub, ID }

        internal long ID { get; private set; }
        internal String Name { get; private set; }
        internal List<Version> Versions { get; private set; }
        internal long ID_TvDB { get; private set; }
        internal long ID_TvRage { get; private set; }
        internal String Name_TvDB { get; private set; }
        internal String Name_TvRage { get; private set; }
        internal String Plot { get; private set; }
        internal String PlotLanguage { get; private set; }
        internal String Banner { get; private set; }
        internal String FolderThumb { get; private set; }
        internal List<Actor> Actors { get; private set; }
        internal List<String> Genres { get; private set; }
        internal long Fans { get; private set; }
        internal DateTime Started { get; private set; }
        internal DateTime Ended { get; private set; }
        internal int Season { get; private set; }
        internal String Classification { get; private set; }
        internal String Country { get; private set; }
        internal String Status { get; private set; }
        internal String Network { get; private set; }
        internal int Runtime { get; private set; }
        internal String Airday { get; private set; }
        internal String Airtime { get; private set; }
        internal Episode LastEpisode { get; private set; }
        internal Episode NextEpisode { get; private set; }

        internal Sub LatestSub { get; private set; }
        internal Order OrderBy { get; private set; }

        internal Show(XmlNode show_node, List<Version> Versions)
        {
            this.Versions = Versions;
            String[] Last=new String[3];
            String[] Next=new String[3];
            foreach (XmlNode sd in show_node.ChildNodes)
            {
                if (sd.InnerText != null)
                {
                    if (sd.Name == "id") ID = long.Parse(sd.InnerText);
                    if (sd.Name == "name") Name = sd.InnerText;
                    if (sd.Name == "id_tvdb") ID_TvDB = long.Parse(sd.InnerText);
                    if (sd.Name == "name_tvdb") Name_TvDB = sd.InnerText;
                    if (sd.Name == "id_tvrage") ID_TvRage = long.Parse(sd.InnerText);
                    if (sd.Name == "name_tvrage") Name_TvRage = sd.InnerText;
                    if (sd.Name == "country") Country = sd.InnerText;
                    if (sd.Name == "classification") Classification = sd.InnerText;
                    if (sd.Name == "network") Network = sd.InnerText;
                    if (sd.Name == "status") Status = sd.InnerText;
                    if (sd.Name == "runtime") Runtime = int.Parse(sd.InnerText);
                    if (sd.Name == "airday") Airday = sd.InnerText;
                    if (sd.Name == "season") Season = int.Parse(sd.InnerText);
                    if (sd.Name == "plot") Plot = sd.InnerText;
                    if (sd.Name == "plotlang") PlotLanguage = sd.InnerText;
                    if (sd.Name == "folder_thumb") FolderThumb = sd.InnerText;
                    if (sd.Name == "banner") Banner = sd.InnerText;
                    if (sd.Name == "actors")
                    {
                        Actors = new List<Actor>();
                        foreach (XmlNode vd in sd.ChildNodes)
                        {
                            Actors.Add(new Actor(vd));
                        }
                    }
                    if (sd.Name == "genres")
                    {
                        Genres = new List<String>();
                        foreach (XmlNode vd in sd.ChildNodes)
                        {
                            if (vd.InnerText != null) Genres.Add(vd.InnerText);
                        }
                    }
                    if (sd.Name == "fans") Fans = int.Parse(sd.InnerText);
                    if (sd.Name == "airtime") Airtime = sd.InnerText;
                    if (sd.Name == "Started")
                    {
                        DateTime data;
                        if (!DateTime.TryParse(sd.InnerText, out data)) data = DateTime.MinValue;
                        Started = data;
                    }
                    if (sd.Name == "ended")
                    {
                        DateTime data;
                        if (!DateTime.TryParse(sd.InnerText, out data)) data = DateTime.MaxValue;
                        Ended = data;
                    }
                    if (sd.Name == "lastep_num") Last[0] = sd.InnerText;
                    if (sd.Name == "lastep_title") Last[1] = sd.InnerText;
                    if (sd.Name == "lastep_date") Last[2] = sd.InnerText;
                    if (sd.Name == "nextep_num") Next[0] = sd.InnerText;
                    if (sd.Name == "nextep_title") Next[1] = sd.InnerText;
                    if (sd.Name == "nextep_date") Next[2] = sd.InnerText;
                }
                
            }
            LatestSub = null;
            OrderBy = Order.ID;
            LastEpisode = new Episode(this.Name, this.ID, Last);
            NextEpisode = new Episode(this.Name, this.ID, Next);
        }

        internal void SetOrder(Order by)
        {
            this.OrderBy = by;
        }

        public override int GetHashCode()
        {
            return (int)this.ID;
        }

        public override string ToString()
        {
            return Name;
        }

        internal void AddSub(Sub s)
        {
            if (s.ShowID == this.ID && this.Versions.Contains(new Version(s.Version)))
            {
                this.Versions[this.Versions.IndexOf(new Version(s.Version))].AddSub(s);
                if (this.LatestSub != null && this.LatestSub.SubmitDate < s.SubmitDate) LatestSub = s;
            }
        }

        internal void ChangeEpisodes(Show s)
        {
            if (this.ID == s.ID)
            {
                if (LastEpisode.Date < s.LastEpisode.Date) LastEpisode = s.LastEpisode;
                if (NextEpisode.Date < s.NextEpisode.Date) NextEpisode = s.NextEpisode;
            }
        }

        internal List<Season> GetSeasons(String version)
        {
            return this.Versions[this.Versions.IndexOf(new Version(version))].Seasons;
        }

        public override bool Equals(object obj)
        {
            if (obj is Show) return this.ID.Equals((obj as Show).ID);
            return false;
        }

        public int CompareTo(object obj)
        {
            if (obj is Show)
            {
                if (OrderBy == Order.ID) return this.ID.CompareTo((obj as Show).ID);
                else if (OrderBy == Order.LastSub && this.LatestSub != null && (obj as Show).LatestSub != null) return this.LatestSub.CompareTo((obj as Show).LatestSub);
            }
            return 0;
        }

        public int CompareTo(Show other)
        {
            if (other == null) throw new ArgumentNullException("other");
            if (OrderBy == Order.ID) return this.ID.CompareTo(other.ID);
            else if (OrderBy == Order.LastSub && this.LatestSub != null && other.LatestSub != null) return this.LatestSub.CompareTo(other.LatestSub);
            throw new InvalidOperationException("other");
        }

        internal String ToLatestString()
        {
            String s = ((String) LastEpisode.Number.Clone()).ToLower();
            if (Genres.Contains("Anime"))
            {
                int x = s.IndexOf('x');
                x++;
                s = s.Remove(0, x);
            }
            else
            {
                s = s.Replace('x', 'E');
                s = "S" + s;
            }
            return s;
        }

        public String ToLabelString()
        {
            return String.Format("{0}\nUltimo Episodio: {1}\nProssimo Episodio: {2}",this.Name,this.LastEpisode.ToString(),this.NextEpisode.ToString());
        }

    }
}
